<?php

namespace scaffold\auth;

use scaffold\exception\LoginException;
use think\Config;
use think\facade\Request;

/**
 * 登录认证
 * @author edward <edward@localhost.com>
 */
class Login
{
    /**
     * 缓存键值前缀
     * @var string
     */
    protected $prefic = 'login_';

    /**
     * 过期时效
     * 默认 30 天
     * @var integer
     */
    protected $expire = 2592000;

    /**
     * token缓存对象
     * @var token
     */
    protected $token;

    /**
     * 登录ID
     * @var string
     */
    protected $loginId;

    /**
     * 登录用户信息
     * @var array
     */
    protected $userInfo = [];

    /**
     * 登录token标识
     * @var string
     */
    protected $loginToken;

    /**
     * 用户类
     * @var class
     */
    protected $userClass;

    /**
     * 获取用户信息函数名
     * @var string
     */
    protected $userGetInfoFunc;

    /**
     * 构造函数
     * @author edward edward@localhost.com
     * @DateTime 2020-08-17
     * @version  1.0.0.0
     *
     * @param    array      $config 配置数组
     */
    public function __construct($config = [])
    {
        $this->init($config);
    }

    /**
     * 初始化加载
     * 缓存键前缀、缓存过期时间
     * 登录用户类、登录用户信息函数
     * 获取loginToken、加载token缓存
     * @author edward edward@localhost.com
     * @DateTime 2020-08-17
     * @version  1.0.0.0
     *
     * @param    array      $options 配置数组
     * @return   $this
     */
    public function init($options = [])
    {
        // 登录缓存键前缀 时效时间
        $this->prefic = isset($options['prefic']) ? $options['prefic'] : $this->prefic;
        $this->expire = isset($options['expire']) ? $options['expire'] : $this->expire;
        // 登录用户信息获取句柄接口
        $this->userClass       = isset($options['user_class']) ? $options['user_class'] : $this->userClass;
        $this->userGetInfoFunc = isset($options['user_get_info_func']) ? $options['user_get_info_func'] : $this->userClass;
        // 登录token
        $this->loginToken = Request::header('Login-Token');
        // token类对象
        $this->token = new Token($this->prefic, $this->expire);
    }

    /**
     * loginToken 赋值
     * @author edward edward@localhost.com
     * @DateTime 2020-08-13
     * @version  1.0.0.0
     *
     * @param    string     $loginToken 登录时效token
     * @return   $this
     */
    public function loginToken($loginToken)
    {
        $this->loginToken = $loginToken;
        return $this;
    }

    /**
     * 登录
     * @author edward edward@localhost.com
     * @DateTime 2020-07-20
     * @version  1.0.0.0
     *
     * @param    string     $id    索引值
     * @return   string            token
     */
    public function login($id)
    {
        $this->loginId = $id;
        return $this->token->signIn($this->loginId);
    }

    /**
     * 登录验证
     * @author edward edward@localhost.com
     * @DateTime 2020-07-20
     * @version  1.0.0.0
     *
     * @return   bool/exception
     */
    public function check()
    {
        if ($this->loginId != $this->token->getIndex($this->loginToken)) {
            throw new LoginException('登录认证不通过');
        }
        return true;
    }

    /**
     * 获取登录ID
     * @author edward edward@localhost.com
     * @DateTime 2020-07-21
     * @version  1.0.0.0
     *
     * @return   integer/string
     */
    public function getLoginId()
    {
        $this->loginId = $this->token->getIndex($this->loginToken);
        return $this->loginId;
    }

    /**
     * 获取登录用户信息
     * @author edward edward@localhost.com
     * @DateTime 2020-08-17
     * @version  1.0.0.0
     *
     * @param    boolean    $force 强制更新
     * @return   array
     */
    public function userInfo($force = false)
    {
        if (empty($this->loginInfo) || $force) {
            $this->loginInfo = call_user_func_array([(new $this->userClass), $this->userGetInfoFunc], [$this->loginId]);
        }
        return $this->loginInfo;
    }

    /**
     * TP 容器加载函数
     * @author edward edward@localhost.com
     * @DateTime 2020-08-19
     * @version  1.0.0.0
     *
     * @param    Config     $config [description]
     * @return   [type]             [description]
     */
    public static function __make(Config $config)
    {
        return new static($config->pull('login'));
    }
}
